سے Gabriel L. Manor Supabase آپ کے ایپ کو ای میل، OAuth، اور جادو لنکس کے لئے داخلہ کی حمایت کے ساتھ تصدیق کو شامل کرنے کے لئے آسان بناتا ہے. لیکن اگرچہ Supabase Auth آپ کے صارفین کے بارے میں کام کرتا ہے، تو آپ کو اکثر ایک تصدیق کی سطح کی ضرورت ہوتی ہے. Supabase built-in auth and Row Level Security (RLS) کے ساتھ ایک عظیم backend پیش کرتا ہے. خاص طور پر ان کی بنیاد پر آسان سے دور ہے fine-grained permissions relationships between users and data آپ ڈیٹا کو ترمیم یا حذف کرنے جیسے کارروائیوں کو وسائل کے مالکان کو محدود کرنا چاہتے ہیں، صارفین کو ان کے اپنے مواد پر ووٹ کرنے سے روکنے، یا مختلف صارف کرداروں کے لئے مختلف اجازتوں کو نافذ کرنا چاہتے ہیں. یہ ٹیوٹوریل چلتا ہے کہ کس طرح لاگو کرنے کے لئے in a اپلی کیشن Supabase authentication and authorization Next.js ہم شروع کریں گے لاگ ان اور سیشن کے انتظام کے لئے، پھر شامل کریں استعمال کریں , enforced through اور A کے Supabase Auth authorization rules روابط پر مبنی رسائی کنٹرول (ReBAC) Supabase Edge Functions local Policy Decision Point (PDP) آخر میں، آپ کے پاس ایک حقیقی وقت کے تعاون کے سروے کے ایپ ہے جو دونوں عوامی اور محفوظ کارروائیوں کی حمایت کرتا ہے - اور ایک انعطاف پذیر لائسنس کے نظام آپ کے ایپ بڑھنے کے طور پر ترقی کر سکتے ہیں. ہم کیا بناتے ہیں اس گائیڈ میں، ہم ایک حقیقی وقت میں ووٹنگ اپلی کیشن کی تعمیر کریں گے اور یہ عمل میں تصدیق اور مجازیت دونوں کو ظاہر کرتا ہے. Supabase Next.js اپلی کیشن صارفین کو سروے بنانے، دوسروں پر ووٹ دینے اور صرف ان کے اپنے مواد کا انتظام کرنے کی اجازت دیتا ہے. login / signup کے لئے اور کس طرح لاگو کرنے کے لئے یہ کنٹرول کرتا ہے جو ووٹ، ترمیم، یا حذف کر سکتے ہیں. Supabase Auth authorization policies ہم Supabase کے بنیادی خصوصیات کا استعمال کریں گے- ، ، ، اور A کے ساتھ مل کر فی صارف اور فی وسائل تک رسائی کے قوانین کو نافذ کرنے کے لئے ماڈل. Auth Postgres RLS Realtime Edge Functions Relationship-Based Access Control (ReBAC) تکنیکی Stack کے کے کے کے کے Supabase – ڈیٹا بیس، تصدیق، حقیقی وقت، اور کنج کے افعال کے لئے بیکنڈ-as-a-service Next.js – اپلی کیشن UI اور API روٹس کی تعمیر کے لئے Frontend فریم ورک Permit.io – (ReBAC کے لئے) PDP کے ذریعہ لائسنسنگ منطق کی وضاحت کرنے کے لئے Supabase CLI - مقامی طور پر اور پیداوار میں Edge Functions کا انتظام اور تنصیب کرنے کے لئے نوٹنگ Next.جیسے کی اجازت زمرہ:CLI Prerequisites کے کے کے کے کے کے Node.js نصب کیا گیا ہے اکاؤنٹ بونس اکاؤنٹ کی اجازت React/Next.js کے بارے میں معلومات پروجیکٹ Repo یہ اپلی کیشن کیا کر سکتا ہے؟ ڈیمو ایپلی کیشن ایک حقیقی وقت میں ووٹنگ پلیٹ فارم ہے جو Next.js اور Supabase کے ساتھ تعمیر کیا گیا ہے، جہاں صارفین ووٹ بن سکتے ہیں اور دوسروں پر ووٹ کرسکتے ہیں. کے کے کے کے کے کسی بھی صارف (مجاز یا نہیں) عوامی سروے کی فہرست دیکھ سکتے ہیں صرف تصدیق شدہ صارفین کو سروے بنانے اور ووٹ کر سکتے ہیں ایک صارف نے پیدا کردہ سروے پر ووٹ نہیں کر سکتے صرف ایک سروے کا تخلیق کرنے والا اسے ترمیم یا حذف کر سکتا ہے Tutorial کا جائزہ لیں ہم ان عام اقدامات پر عمل کریں گے: کے کے کے کے کے کے Supabase پروجیکٹ، schema، auth، اور RLS کو قائم کریں ایپ کی بنیادی خصوصیات بنائیں جیسے سروے کی تخلیق اور ووٹنگ Permit.io میں نقشے اور قواعد کا تعین کرنے کے لئے ماڈل لائسنس کے قوانین صارفین کو سائن اپ کرنے کے لئے Supabase Edge Functions پیدا کریں، نقشے کا تعین کریں، اور اجازتوں کی جانچ پڑتال کریں اپلی کیشن کے Frontend میں پالیسیوں کو ان Edge فائلوں کا استعمال کرتے ہوئے لاگو کریں شروع کریں - Setting up Supabase in the Project پروجیکٹ میں Supabase کی تشکیل اختیاری: Clone the Starter Template I've already created a ہے تمام کوڈ کے ساتھ آپ کو شروع کرنے کی ضرورت ہے تاکہ ہم Supabase اور Permit.io کو نافذ کرنے پر توجہ مرکوز کرسکتے ہیں. Temple کے آغاز GitHub آپ مندرجہ ذیل کمانڈ کو چلانے کے ذریعے منصوبہ کو کلن کرسکتے ہیں: git clone <https://github.com/permitio/supabase-fine-grained-authorization> ایک بار جب آپ پروجیکٹ کینسر کر چکے ہیں تو، پروجیکٹ ڈائریکٹری میں رجسٹریشن کریں اور انفرادیات کو انسٹال کریں: cd realtime-polling-app-nextjs-supabase-permitio npm install Supabase میں ایک نیا منصوبہ بنائیں شروع کرنے کے لئے: کے کے کے کے https://supabase.com پر جائیں اور لاگ ان کریں یا ایک اکاؤنٹ بنائیں. "نئی پروجیکٹ" پر کلک کریں اور اپنے پروجیکٹ کا نام، پاس ورڈ اور علاقے درج کریں. ایک بار پیدا ہونے کے بعد، پروجیکٹ ترتیبات → API پر جائیں اور اپنے پروجیکٹ URL اور Anon Key کو نوٹ کریں - آپ کو بعد میں ان کی ضرورت ہوگی. Supabase میں تصدیق اور ڈیٹا بیس کی تشکیل ہم Supabase کے داخلہ ای میل / پاس ورڈ auth استعمال کریں گے: کے کے sidebar میں، Authentication → Providers پر جائیں ای میل فراہم کرنے والے کو فعال کریں (مختصر) ٹیسٹ کے لئے ای میل کی تصدیق کو غیر فعال کریں، لیکن پیداوار کے لئے اسے فعال رکھیں ڈیٹا بیس کے نظام کی تخلیق یہ اپلی کیشن تین اہم ٹیبلز کا استعمال کرتا ہے: ، اور استعمال کریں The Supabase Dashboard پر اور مندرجہ ذیل کو چلائیں: polls options votes SQL Editor -- Create a polls table CREATE TABLE polls ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, question TEXT NOT NULL, created_by UUID REFERENCES auth.users(id) NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc', NOW()), creator_name TEXT NOT NULL, expires_at TIMESTAMP WITH TIME ZONE NOT NULL, ); -- Create an options table CREATE TABLE options ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, poll_id UUID REFERENCES polls(id) ON DELETE CASCADE, text TEXT NOT NULL, ); -- Create a votes table CREATE TABLE votes ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, poll_id UUID REFERENCES polls(id) ON DELETE CASCADE, option_id UUID REFERENCES options(id) ON DELETE CASCADE, user_id UUID REFERENCES auth.users(id), created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc', NOW()), UNIQUE(poll_id, user_id) ); راؤنڈ سطح کی حفاظت (RLS) کی اجازت for each table and define policies: RLS کے -- Polls policies ALTER TABLE polls ENABLE ROW LEVEL SECURITY; CREATE POLICY "Anyone can view polls" ON polls FOR SELECT USING (true); CREATE POLICY "Authenticated users can create polls" ON polls FOR INSERT TO authenticated WITH CHECK (auth.uid() = created_by); -- Options policies ALTER TABLE options ENABLE ROW LEVEL SECURITY; CREATE POLICY "Anyone can view options" ON options FOR SELECT USING (true); CREATE POLICY "Poll creators can add options" ON options FOR INSERT TO authenticated WITH CHECK ( EXISTS ( SELECT 1 FROM polls WHERE id = options.poll_id AND created_by = auth.uid() ) ); -- Votes policies ALTER TABLE votes ENABLE ROW LEVEL SECURITY; CREATE POLICY "Anyone can view votes" ON votes FOR SELECT USING (true); CREATE POLICY "Authenticated users can vote once" ON votes FOR INSERT TO authenticated WITH CHECK ( auth.uid() = user_id AND NOT EXISTS ( SELECT 1 FROM polls WHERE id = votes.poll_id AND created_by = auth.uid() ) ); Supabase کے حقیقی وقت کی خصوصیات کا استعمال کرنے کے لئے: کے کے کے سائیڈر میں، ٹیبل ایڈیٹر پر جائیں تین ٹیبلوں (پیلنگز، اختیارات، ووٹوں) کے لئے: تین پوائنٹس پر کلک کریں → ٹیبل Toggle کو ترمیم کریں "Realtime کو فعال کریں" تبدیلیوں کو محفوظ کریں اپلی کیشن میں Supabase Email Authentication اس ڈیمو ایپ میں، کوئی بھی اپلی کیشن پر دستیاب سروے کی فہرست کو دیکھ سکتا ہے، فعال اور ختم شدہ دونوں. ایک سروے کی تفصیلات کو دیکھنے کے لئے، کسی بھی سروے پر انتظام، یا ووٹ کرنے کے لئے، صارف کو لاگ ان ہونا ضروری ہے. ہم اس منصوبے کے لئے تصدیق کے ذریعہ ای میل اور پاس ورڈ کا استعمال کریں گے. : : .env.local NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key آپ کے لاگ ان اجزاء کو اپ ڈیٹ کریں اور ای میل / پاس ورڈ کے ذریعے سائن اپ اور لاگ ان دونوں کو منظم کریں: import { useState } from "react"; import { createClient } from "@/utils/supabase/component"; const LogInButton = () => { const supabase = createClient(); async function logIn() { const { error } = await supabase.auth.signInWithPassword({ email, password, }); if (error) { setError(error.message); } else { setShowModal(false); } } async function signUp() { const { error } = await supabase.auth.signUp({ email, password, options: { data: { user_name: userName, }, }, }); if (error) { setError(error.message); } else { setShowModal(false); } } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); if (isLogin) { await logIn(); } else { await signUp(); } }; return ( <> <button onClick={() => setShowModal(true)} className="flex items-center gap-2 p-2 bg-gray-800 text-white rounded-md"> Log In </button> ... </> ); }; export default LogInButton; یہاں، ہم Supabase کا استعمال کرتے ہیں ایک صارف پر لاگ ان کرنے کا طریقہ اور ایک نیا صارف کو ان کے ای میل اور پاس ورڈ کے ساتھ رجسٹر کرنے کا طریقہ. ہم بھی صارف کے نام کو ذخیرہ کر رہے ہیں صارف کے میٹا ڈیٹا میں. signInWithPassword signUp user_name آپ بھی استعمال کر سکتے ہیں صارفین کو لاگ ان کرنے اور ان کو ہدایت کرنے کے لئے: supabase.auth.signOut() import { createClient } from "@/utils/supabase/component"; import { useRouter } from "next/router"; const LogOutButton = ({ closeDropdown }: { closeDropdown: () => void }) => { const router = useRouter(); const supabase = createClient(); const handleLogOut = async () => { await supabase.auth.signOut(); closeDropdown(); router.push("/"); }; return ( ... ); }; export default LogOutButton; یہاں، ہم استعمال کرتے ہیں Supabase سے طریقہ کار صارف کو لاگ ان کرنے اور ان کو ہوم پیج پر ہدایت کرنے کے لئے. signOut صارف کی تصدیق کی حالت میں تبدیلیوں کے لئے سننے Listening for changes in the user's authentication state allows us to update the UI based on the user's authentication status. This allows you to: کے کے کے کے دکھائیں / login / logout بٹن جیسے UI عناصر چھپائیں محفوظ صفحات تک رسائی کو محدود کریں (مثال کے طور پر ووٹنگ یا سروے کا انتظام) یقینی بنائیں کہ صرف تصدیق شدہ صارفین محدود کارروائیوں کو انجام دے سکتے ہیں ہم استعمال کریں گے to listen to these events and update the app accordingly. supabase.auth.onAuthStateChange() کے کے In the Layout.tsx file: Track Global Auth State import React, { useEffect, useState } from "react"; import { createClient } from "@/utils/supabase/component"; import { User } from "@supabase/supabase-js"; const Layout = ({ children }: { children: React.ReactNode }) => { const [user, setUser] = useState<User | null>(null); useEffect(() => { const fetchUser = async () => { const supabase = createClient(); const { data } = supabase.auth.onAuthStateChange((event, session) => { setUser(session?.user || null); }); return () => { data.subscription.unsubscribe(); }; }; fetchUser(); }, []); return ( ... ); }; export default Layout; Restrict Access on Protected Pages جیسے صفحات یا آپ کو بھی ان کی تصدیق کی حالت میں تبدیلیوں کو سننا چاہئے تاکہ غیر تصدیق شدہ صارفین ان تک رسائی حاصل کرنے سے روکیں. poll details poll management یہ ہے کہ یہ کس طرح میں نظر آتا ہے : : pages/polls/[id].tsx import { createClient } from "@/utils/supabase/component"; import { User } from "@supabase/supabase-js"; const Page = () => { const [user, setUser] = useState<User | null>(null); useEffect(() => { const fetchUser = async () => { const supabase = createClient(); const { data } = supabase.auth.onAuthStateChange((event, session) => { setUser(session?.user || null); setLoading(false); }); return () => { data.subscription.unsubscribe(); }; }; fetchUser(); }, []); return ( ... ); export default Page; And a similar pattern applies in , where users should only see their own polls if logged in: pages/polls/manage.tsx import { createClient } from "@/utils/supabase/component"; import { User } from "@supabase/supabase-js"; const Page = () => { const [user, setUser] = useState<User | null>(null); const supabase = createClient(); useEffect(() => { const fetchUser = async () => { const { data } = supabase.auth.onAuthStateChange((event, session) => { setUser(session?.user || null); if (!session?.user) { setLoading(false); } }); return () => { data.subscription.unsubscribe(); }; }; fetchUser(); }, []); return ( ... ); }; export default Page; یہ نمونے اس بات کو یقینی بناتے ہیں کہ آپ کا UI صارف کی موجودہ تصدیق کی حیثیت کا تعین کرتا ہے اور ہم بعد میں شامل کرنے والے تصدیق چیک کے لئے بنیاد بناتا ہے. Object جب آپ کو کال کریں Edge Function to determine whether a user is allowed to vote or manage a specific poll. user checkPermission Polling App کی سرگرمیوں کی تعمیر Supabase کی ترتیب اور تصدیق کے کام کے ساتھ، ہم اب ووٹنگ ایپ کے بنیادی سرگرمیوں کو تعمیر کرسکتے ہیں. کے کے کے کے نئے سروے بنائیں حقیقی وقت میں سروے کی فہرست اور دکھائیں ایک ووٹنگ کا نظام This gives us the basic app behavior that we’ll soon protect with fine-grained permissions. نئے سروے بنائیں صارفین کو سروے بنانے کے لئے لاگ ان ہونا ضروری ہے. ہر سروے میں ایک سوال، ایک اختتام کی تاریخ اور ایک سیٹ اختیارات شامل ہیں. ہم یہ بھی ریکارڈ کرتے ہیں کہ کس نے سروے کو پیدا کیا تاکہ ہم بعد میں اس رشتے کو رسائی کنٹرول کے لئے استعمال کرسکتے ہیں. اندر , fetch the authenticated user, and use Supabase to insert the poll and its options: NewPoll.tsx import React, { useEffect, useState } from "react"; import { createClient } from "@/utils/supabase/component"; import { User } from "@supabase/supabase-js"; const NewPoll = () => { const [user, setUser] = useState<User | null>(null); const supabase = createClient(); useEffect(() => { const fetchUser = async () => { const supabase = createClient(); const { data } = supabase.auth.onAuthStateChange((event, session) => { setUser(session?.user || null); }); return () => { data.subscription.unsubscribe(); }; }; fetchUser(); }, []); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (question.trim() && options.filter(opt => opt.trim()).length < 2) { setErrorMessage("Please provide a question and at least two options."); return; } // Create the poll const { data: poll, error: pollError } = await supabase .from("polls") .insert({ question, expires_at: new Date(expiryDate).toISOString(), created_by: user?.id, creator_name: user?.user_metadata?.user_name, }) .select() .single(); if (pollError) { console.error("Error creating poll:", pollError); setErrorMessage(pollError.message); return; } // Create the options const { error: optionsError } = await supabase.from("options").insert( options .filter(opt => opt.trim()) .map(text => ({ poll_id: poll.id, text, })) ); if (!optionsError) { setSuccessMessage("Poll created successfully!"); handleCancel(); } else { console.error("Error creating options:", optionsError); setErrorMessage(optionsError.message); } }; return ( ... ); }; export default NewPoll; ہم بعد میں Permit.io میں "Creator" کردار کو توسیع کرنے کے لئے یہاں ایک Edge Function کال کریں گے. Polls کو تلاش اور دکھائیں سروے میں تقسیم کیا گیا (مجھے ابھی تک نہیں مل سکا) اور (expired). You can fetch them using Supabase queries filtered by the current timestamp, and set up real-time subscriptions to reflect changes instantly. active past مثال سے : : pages/index.tsx import { PollProps } from "@/helpers"; import { createClient } from "@/utils/supabase/component"; export default function Home() { const supabase = createClient(); useEffect(() => { const fetchPolls = async () => { setLoading(true); const now = new Date().toISOString(); try { // Fetch active polls const { data: activePolls, error: activeError } = await supabase .from("polls") .select( ` id, question, expires_at, creator_name, created_by, votes (count) ` ) .gte("expires_at", now) .order("created_at", { ascending: false }); if (activeError) { console.error("Error fetching active polls:", activeError); return; } // Fetch past polls const { data: expiredPolls, error: pastError } = await supabase .from("polls") .select( ` id, question, expires_at, creator_name, created_by, votes (count) ` ) .lt("expires_at", now) .order("created_at", { ascending: false }); if (pastError) { console.error("Error fetching past polls:", pastError); return; } setCurrentPolls(activePolls); setPastPolls(expiredPolls); } catch (error) { console.error("Unexpected error fetching polls:", error); } finally { setLoading(false); } }; fetchPolls(); // Set up real-time subscription on the polls table: const channel = supabase .channel("polls") .on( "postgres_changes", { event: "*", schema: "public", table: "polls", }, fetchPolls ) .subscribe(); return () => { supabase.removeChannel(channel); }; }, []); return ( ... ); } صارفین کے سروے کو دیکھیں اور منظم کریں یہاں، ہم فعال اور ماضی کے سروے سے حاصل کر رہے ہیں Supabase.We are also setting up a real-time subscription to listen for changes in the table so that we can update the UI with the latest poll data. To differentiate between active and past polls, we are comparing the expiry date of each poll with the current date. polls polls اپ ڈیٹ کریں صفحہ حاصل کرنے اور صرف صارف کی طرف سے پیدا کردہ سروے کو ظاہر کرنے کے لئے: pages/manage.tsx import { PollProps } from "@/helpers"; const Page = () => { useEffect(() => { if (!user?.id) return; const fetchPolls = async () => { try { const { data, error } = await supabase .from("polls") .select( ` id, question, expires_at, creator_name, created_by, votes (count) ` ) .eq("created_by", user.id) .order("created_at", { ascending: false }); if (error) { console.error("Error fetching polls:", error); return; } setPolls(data || []); } catch (error) { console.error("Unexpected error fetching polls:", error); } finally { setLoading(false); } }; fetchPolls(); // Set up real-time subscription const channel = supabase .channel(`polls_${user.id}`) .on( "postgres_changes", { event: "*", schema: "public", table: "polls", filter: `created_by=eq.${user.id}`, }, fetchPolls ) .subscribe(); return () => { supabase.removeChannel(channel); }; }, [user]); return ( ... ); }; export default Page; Here, we only fetch polls created by the user and listen for real-time updates in the table so that the UI is updated with the latest poll data. polls اس کے علاوہ، اپ ڈیٹ اس طرح، اگر ایک لاگ ان شدہ صارف سروے کی تخلیق کرنے والا ہے تو، سروے کو ترمیم اور حذف کرنے کے لئے علامتیں ان کو سروے میں دکھایا جائے گا. PollCard import { createClient } from "@/utils/supabase/component"; import { User } from "@supabase/supabase-js"; const PollCard = ({ poll }: { poll: PollProps }) => { const [user, setUser] = useState<User | null>(null); useEffect(() => { const supabase = createClient(); const fetchUser = async () => { const { data } = supabase.auth.onAuthStateChange((event, session) => { setUser(session?.user || null); setLoading(false); }); return () => { data.subscription.unsubscribe(); }; }; fetchUser(); }, []); return ( ... )} </Link> ); }; export default PollCard; لہذا اب، ایک سروے کارڈ پر، اگر لاگ ان کردہ صارف سروے کا تخلیق کرنے والا ہے تو، سروے کو ترمیم اور حذف کرنے کے لئے آئکنز ان کو دکھایا جائے گا. ووٹنگ کے نظام کا استعمال ووٹنگ کی منطق کے مطابق: کے کے کے کے ہر صارف کے لئے صرف ایک ووٹ تخلیق کار اپنے سروے پر ووٹ نہیں کرسکتے Votes are stored in the table votes نتائج واقعی وقت میں دکھایا جاتا ہے اور اپ ڈیٹ کیا جاتا ہے ہمیں یہ بتائیں کہ یہ کس طرح کام کرتا ہے component: ViewPoll.tsx ہم اس وقت کے صارف کے ID کو منتخب کرنے کے لئے ووٹنگ کی صلاحیت اور ان کی ووٹنگ کی ریکارڈ کرنے کی ضرورت ہے. Fetch the Logged-In User import { createClient } from "@/utils/supabase/component"; import { User } from "@supabase/supabase-js"; const ViewPoll = () => { const [user, setUser] = useState<User | null>(null); const supabase = createClient(); useEffect(() const fetchUser = async () => { const { data: { user }, } = await supabase.auth.getUser(); setUser(user); }; fetchUser(); }, []); جب ہم صارف کو حاصل کرتے ہیں، ہم: Load Poll Details and Check Voting Status کے کے کے انٹرویو خود (مقابلہ اختیارات اور ووٹ کا حساب بھی شامل ہے) Whether this user has already voted ہم بھی ان کو دوبارہ بعد میں حقیقی وقت کے اپ ڈیٹس میں کال کریں گے. useEffect(() => { if (!user) { return; } const checkUserVote = async () => { const { data: votes } = await supabase .from("votes") .select("id") .eq("poll_id", query.id) .eq("user_id", user.id) .single(); setHasVoted(!!votes); setVoteLoading(false); }; const fetchPoll = async () => { const { data } = await supabase .from("polls") .select( ` *, options ( id, text, votes (count) ) ` ) .eq("id", query.id) .single(); setPoll(data); setPollLoading(false); checkUserVote(); }; fetchPoll(); Listen for Real-Time Updates ہم تبدیلیوں میں شامل ہیں جب ایک نیا ووٹ دیا جاتا ہے تو، ہم اپ ڈیٹ ووٹنگ ڈیٹا اور ووٹنگ کی حالت حاصل کرتے ہیں. votes const channel = supabase .channel(`poll-${query.id}`) .on( "postgres_changes", { event: "*", schema: "public", table: "votes", filter: `poll_id=eq.${query.id}`, }, () => { fetchPoll(); checkUserVote(); } ) .subscribe(); return () => { supabase.removeChannel(channel); }; }, [query.id, user]); Handle the Vote Submission If the user hasn’t voted and is allowed to vote (we’ll add a permission check later), we insert their vote. const handleVote = async (optionId: string) => { if (!user) return; try { const { error } = await supabase.from("votes").insert({ poll_id: query.id, option_id: optionId, user_id: user.id, }); if (!error) { setHasVoted(true); } } catch (error) { console.error("Error voting:", error); } }; ہم تمام ووٹوں کی کل تعداد اور ختم ہونے کا وقت پر ایک بونس کی تعداد کا حساب کرتے ہیں. آپ اس کے بعد ترقی کے بارز یا اعداد و شمار کو ظاہر کرنے کے لئے اس کا استعمال کرسکتے ہیں. Display the Poll Results if (!poll || pollLoading || voteLoading) return <div>Loading...</div>; // 6. calculate total votes const totalVotes = calculateTotalVotes(poll.options); const countdown = getCountdown(poll.expires_at); return ( ... ); }; export default ViewPoll; اس ترتیبات کے ساتھ، آپ کا ووٹنگ سسٹم مکمل طور پر کام کرتا ہے. لیکن اب، جو بھی لاگ ان کرسکتے ہیں، تکنیکی طور پر ووٹنگ کرنے کی کوشش کرسکتے ہیں - یہاں تک کہ ان کے اپنے ووٹنگ میں بھی. استعمال کریں اور ان قوانین کو پورا کرنے کے لئے. authorization checks Permit.io Supabase Edge Functions ہم ایسا کرنے سے پہلے، ہم سب سے پہلے اس قسم کی ذمہ داری کی سطح پر نظر ڈالیں جو ہم لاگو کرنے جا رہے ہیں. ReBAC (Relationship-Based Access Control) کا استعمال کرتے ہوئے Supabase handles authentication and basic row-level permissions well, but it doesn’t support complex rules like: کے کے کے کے Preventing users from voting on their own polls ایک مخصوص سروے کے لئے "Creator" کے طور پر (مثال کے طور پر) بیرونی پالیسیوں کے ذریعے رسائی کا انتظام ان قسم کے رشتے پر مبنی اجازتوں کی حمایت کرنے کے لئے، ہم Permit.io کے ساتھ ReBAC کو انسٹال کریں گے. صارفین اور وسائل کے درمیان تعلقات کی بنیاد پر اجازتوں کا انتظام کرنے کے لئے ایک ماڈل ہے اور صرف کرداروں یا خصوصیات پر بھروسہ کرنے کے بجائے (جیسا کہ RBAC یا ABAC میں)، ReBAC اس طریقے سے رسائی کا تعین کرتا ہے کہ ایک صارف کس طرح اس وسائل سے منسلک ہے جسے وہ رسائی حاصل کرنے کی کوشش کر رہے ہیں. روابط پر مبنی رسائی کنٹرول (ReBAC) روابط پر مبنی رسائی کنٹرول (ReBAC) In this tutorial, we apply ReBAC to a polling app: کے کے کے ایک صارف جو ایک سروے بناتا ہے وہ صرف وہ ہے جو اس کا انتظام کر سکتا ہے (مزید / حذف) A user vote on their poll cannot own دیگر تصدیق شدہ صارفین ہر سروے میں ایک بار ووٹ کر سکتے ہیں By modeling these relationships in Permit.io, we can define fine-grained access rules that go beyond Supabase’s built-in Row Level Security (RLS). We’ll enforce them at runtime using Supabase Edge Functions and Permit’s policy engine. ReBAC پر مزید کے لئے، چیک کریں . Permit.io کے ReBAC دستاویز رسائی کنٹرول ڈیزائن For our Polling app, we will define: کے کے کے ایک ذریعہ جس میں وسائل کی مخصوص کارروائی ہوتی ہے: سروے: پیدا کریں، پڑھیں، حذف کریں، اپ ڈیٹ کریں. Two roles for granting permission levels based on a user’s relationship with the resources: Can perform and actions in polls. Can not , or actions in polls. authenticated: create read delete update Can , , , and actions in polls. Can perform and actions in votes. Cannot use on their own polls. creator: create read delete update read create create Permit.io کو اپ لوڈ کریں براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی. کے کے کے Permit.io میں ایک نیا منصوبہ بنائیں اس کا نام کچھ supabase-polling کی طرح ہے Define the polls resource Go to the tab Policy → Resources Click “Create Resource” Name it , and add the actions: , , , polls read create update delete Resource کے لئے ReBAC کو فعال کریں "ReBAC اختیارات" کے تحت، مندرجہ ذیل کرداروں کو مقرر کریں: تصدیق شدہ تخلیق کار Click Save ایک نیا منصوبہ بنائیں ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیسے ،جیس ، ، ) that are unnecessary for this tutorial. admin editor user کے کے کے رسائی کی پالیسیوں کا تعین کریں پالیسیوں ٹیب پر جائیں Visual matrix کا استعمال کریں: authenticated کر سکتے ہیں پڑھنے اور پیدا کرنے کے لئے سروے کی تخلیق کر سکتے ہیں پڑھنے، اپ ڈیٹ اور حذف کرنے کے لئے سروے (مزید) آپ اس کے حصے کے طور پر ووٹ کی اجازتوں کو ترتیب دے سکتے ہیں یا ایک دوسرا وسائل کے ذریعہ اگر آپ الگ الگ الگ ووٹ ماڈل کر سکتے ہیں ذریعہ انسٹینز شامل کریں ڈائریکٹری میں جائیں → انسٹینز ذاتی سروے ایڈز کو ذریعہ انسٹینز کے طور پر شامل کریں (آپ نئے سروے بنائے جاتے وقت اس کے بعد خود کار طریقے سے کریں گے) سروے پر صارفین کو کردار ادا کریں (مثال کے طور پر، user123 سروے 456 کی تخلیق کرنے والا ہے) اس ساخت نے ہمیں فکسڈ رسائی کے قوانین لکھنے اور ہر صارف، ہر سروے پر ان کی اطلاق کرنے کی صلاحیت دی. اب کہ ہم اجازت ڈسپلے پر ابتدائی تنصیب مکمل کر چکے ہیں، ہمیں اس کا استعمال ہمارے ایپلی کیشن میں کریں. ہمارے Supabase پروجیکٹ کو Edge Functions کے ذریعے جو: کی اجازت کے کے کے Sync نئے صارفین Assign creator roles درخواست پر رسائی کی جانچ پڑتال Setting up Permit in the Polling Application اجازت آپ کے ایپلی کیشن کے ساتھ انضمام کرنے کے کئی طریقے پیش کرتا ہے، لیکن ہم اس ٹیوٹوریل کے لئے کنٹینر PDP کا استعمال کریں گے. آپ کو اس کنٹینر کو آن لائن ہوسٹ کرنے کی ضرورت ہے تاکہ آپ اس تک رسائی حاصل کرسکتے ہیں Supabase Edge افعال. ایک بار جب آپ اسے میزبان کرتے ہیں تو، اپنے کنٹینر کے لئے url محفوظ کریں. railway.com آپ کی اجازت API کلید حاصل کرسکتے ہیں "Projects" پر کلک کرتے ہوئے اجازت ڈسپلے بیل میں، آپ کے کام کر رہے ہیں کہ منصوبہ پر سواری، تین پوائنٹس پر کلک کریں، اور "Copy API Key" کا انتخاب کریں. Authorization کے لئے Supabase Edge Function API Permit.io جیسے تیسرے فریق کی خدمات کو منسلک کرنے کے لئے بہترین ہیں. ہم ان کا استعمال کریں گے کہ صارفین کو سروے پر مخصوص کارروائیوں کو انجام دینے کی اجازت ہے یا نہیں کی جانچ پڑتال کرتے ہوئے چلانے کے وقت ہمارے ReBAC قوانین کو نافذ کریں. Supabase Edge Functions Create Functions in Supabase آپ کے منصوبے میں Supabase کو ابتدائی کریں اور اس کا استعمال کرتے ہوئے تین مختلف افعال بنائیں command. These will be the starting point for your functions: supabase functions new npx supabase init npx supabase functions new syncUser npx supabase functions new updateCreatorRole npx supabase functions new checkPermission یہ پیدا کرے گا ایک فہرست میں اب، ہم ہر نقطہ کے لئے کوڈ لکھیں. functions supabase زمرہ:تصویر میں زمرہ:تصویر میں زمرہ:تصویر میں زمرہ: ) کے syncUser.ts یہ فہرست Supabase's کے لئے ہے جب ایک نیا صارف لاگ ان کرتا ہے، ہم Permit.io پر ان کی شناخت سائن اپ کرتے ہیں اور ان کو معاوضہ فراہم کرتے ہیں نقشہ SIGNED_UP authenticated import "jsr:@supabase/functions-js/edge-runtime.d.ts"; import { Permit } from "npm:permitio"; const corsHeaders = { 'Access-Control-Allow-Origin': "*", 'Access-Control-Allow-Headers': 'Authorization, x-client-info, apikey, Content-Type', 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE', } // Supabase Edge Function to sync new users with Permit.io Deno.serve(async (req) => { const permit = new Permit({ token: Deno.env.get("PERMIT_API_KEY"), pdp: "<https://real-time-polling-app-production.up.railway.app>", }); try { const { event, user } = await req.json(); // Only proceed if the event type is "SIGNED_UP" if (event === "SIGNED_UP" && user) { const newUser = { key: user.id, email: user.email, name: user.user_metadata?.name || "Someone", }; // Sync the user to Permit.io await permit.api.createUser(newUser); await permit.api.assignRole({ role: "authenticated", tenant: "default", user: user.id, }); console.log(`User ${user.email} synced to Permit.io successfully.`); } // Return success response return new Response( JSON.stringify({ message: "User synced successfully!" }), { status: 200, headers: corsHeaders }, ); } catch (error) { console.error("Error syncing user to Permit: ", error); return new Response( JSON.stringify({ message: "Error syncing user to Permit.", "error": error }), { status: 500, headers: { "Content-Type": "application/json" } }, ); } }); مصنوعات کی تعمیر کا طریقہ ( ) کے updateCreatorRole.ts ایک بار جب ایک صارف نے ایک سروے تخلیق کی ہے تو، اس تقریب کو کہا جاتا ہے: کے کے کے ایک نیا Permit.io وسائل انٹرفیس کے طور پر سروے کو سائن اپ کریں : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : چیک کریں ( ) checkPermission.ts اس کا مطلب یہ ہے کہ اس کا مطلب یہ ہے کہ اس کا استعمال کرتے ہوئے کسی بھی صارف کو اس کا استعمال کرنے کی اجازت دی جاتی ہے ( ، ، ، ایک خاص سوال میں create read update delete import "jsr:@supabase/functions-js/edge-runtime.d.ts"; import { Permit } from "npm:permitio"; const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Authorization, x-client-info, apikey, Content-Type", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE", }; Deno.serve(async req => { const permit = new Permit({ token: Deno.env.get("PERMIT_API_KEY"), pdp: "<https://real-time-polling-app-production.up.railway.app>", }); try { const { userId, operation, key } = await req.json(); // Validate input parameters if (!userId || !operation || !key) { return new Response( JSON.stringify({ error: "Missing required parameters." }), { status: 400, headers: { "Content-Type": "application/json" } } ); } // Check permissions using Permit's ReBAC const permitted = await permit.check(userId, operation, { type: "polls", key, tenant: "default", // Include any additional attributes that Permit needs for relationship checking attributes: { createdBy: userId, // This will be used in Permit's policy rules }, }); return new Response(JSON.stringify({ permitted }), { status: 200, headers: corsHeaders, }); } catch (error) { console.error("Error checking user permission: ", error); return new Response( JSON.stringify({ message: "Error occurred while checking user permission.", error: error, }), { status: 500, headers: { "Content-Type": "application/json" } } ); } }); مقامی ٹیسٹ مقامی طور پر افعال کا تجربہ کرنے کے لئے آپ کے Supabase ڈی وی سرور کو شروع کریں: npx supabase start npx supabase functions serve آپ اس کے بعد آپ کے افعال پر کلک کر سکتے ہیں: <http://localhost:54321/functions/v1/><function-name> مثال کے: <http://localhost:54321/functions/v1/checkPermission> UI میں لائسنس کی جانچ پڑتال اب کہ ہم نے Permit.io کے ساتھ ہماری لائسنسنگ منطق تخلیق کی ہے اور Supabase Edge Functions کے ذریعے اسے ظاہر کیا ہے، یہ اپلی کیشن کے اجزاء میں ان چیکوں کو نافذ کرنے کا وقت ہے. اس سیکشن میں، ہم ان افعال کو کال کرنے کے لئے اہم UI اجزاء کو اپ ڈیٹ کریں گے اور شرط سے صارفین کی کارروائیوں کو اجازت یا بلاک کریں گے جیسے ووٹنگ یا اجازت کی جانچ پڑتال پر مبنی سروے کا انتظام کریں گے. : Creator Role Assign کے بعد Poll Creation ٹائپنگ.tsx ٹائپنگ.tsx ایک سروے تخلیق کرنے اور اسے Supabase میں ذخیرہ کرنے کے بعد، ہم کام کرنے کے لئے: updateCreatorRole کے کے Sync the new poll as a resource in Permit.io Assign the current user the role for that specific poll creator const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (question.trim() && options.filter(opt => opt.trim()).length < 2) { setErrorMessage("Please provide a question and at least two options."); return; } try { // Create the poll const { data: poll, error: pollError } = await supabase .from("polls") .insert({ question, expires_at: new Date(expiryDate).toISOString(), created_by: user?.id, creator_name: user?.user_metadata?.user_name, }) .select() .single(); if (pollError) { console.error("Error creating poll:", pollError); setErrorMessage(pollError.message); return; } // Create the options const { error: optionsError } = await supabase.from("options").insert( options .filter(opt => opt.trim()) .map(text => ({ poll_id: poll.id, text, })) ); if (optionsError) { console.error("Error creating options:", optionsError); setErrorMessage(optionsError.message); return; } // Update the creator role in Permit.io const response = await fetch( "<http://127.0.0.1:54321/functions/v1//updateCreatorRole>", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userId: user?.id, pollId: poll.id, }), } ); const { success, error } = await response.json(); if (!success) { console.error("Error updating creator role:", error); // Note: We don't set an error message here as the poll was still created successfully } setSuccessMessage("Poll created successfully!"); handleCancel(); } catch (error) { console.error("Error in poll creation process:", error); setErrorMessage("An unexpected error occurred while creating the poll."); } }; : اجازت کی بنیاد پر ووٹنگ کی محدودیت ViewPoll.tsx ایک صارف کو ایک سروے میں ووٹ کرنے کی اجازت دینے سے پہلے، ہم اس بات کی تصدیق کرنے کے لئے کہ ان کے پاس کی اجازت کے لئے اس طرح ہم قواعد کو نافذ کرتے ہیں: checkPermission create votes “A creator cannot vote on their own poll.” Check voting permission: const [canVote, setCanVote] = useState(false); useEffect(() => { const checkPermission = async () => { if (!user || !query.id) return; try { const response = await fetch("<http://127.0.0.1:54321/functions/v1/checkPermission>", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userId: user.id, operation: "create", key: query.id, }), }); const { permitted } = await response.json(); setCanVote(permitted); } catch (error) { console.error("Error checking permission:", error); setCanVote(false); } }; checkPermission(); }, [user, query.id]); Disable vote buttons if user isn’t allowed: <button onClick={() => handleVote(option.id)} disabled={!user || !canVote}} className="w-full text-left p-4 rounded-md hover:bg-slate-100 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"> {option.text} </button> Show a message if the user is not allowed to vote: {user && !canVote && ( <p className="mt-4 text-gray-600">You cannot vote on your own poll</p> )} Control Access to Edit/Delete کا استعمال کریں PollCard.tsx ہم سائن اپ مینجمنٹ کارروائیوں کو بھی محدود کرتے ہیں (معدل کریں اور حذف کریں) اس بات کو چیک کرتے ہوئے کہ کیا صارف نے یا اس درخواست کے لئے اجازت update delete Check management permissions: const [canManagePoll, setCanManagePoll] = useState(false); useEffect(() => { const checkPollPermissions = async () => { if (!user || !poll.id) return; try { // Check for both edit and delete permissions const [editResponse, deleteResponse] = await Promise.all([ fetch("<http://127.0.0.1:54321/functions/v1/checkPermission>", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userId: user.id, operation: "update", key: poll.id, }), }), fetch("/api/checkPermission", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userId: user.id, operation: "delete", key: poll.id, }), }), ]); const [{ permitted: canEdit }, { permitted: canDelete }] = await Promise.all([editResponse.json(), deleteResponse.json()]); // User can manage poll if they have either edit or delete permission setCanManagePoll(canEdit || canDelete); } catch (error) { console.error("Error checking permissions:", error); setCanManagePoll(false); } }; checkPollPermissions(); }, [user, poll.id]); Conditionally show management buttons: تبدیل کریں : {user?.id === poll?.created_by && ( کے ساتھ: {canManagePoll && ( <div className="flex justify-start gap-4 mt-4"> <button type="button" onClick={handleEdit}> </button> <button type="button" onClick={handleDelete}> </button> </div> )} انضمام کا تجربہ ایک بار انضمام، آپ کو اپلی کیشن میں مندرجہ ذیل رویے دیکھنا چاہئے: کے کے کے کے لاگ ان شدہ صارفین سروے کو دیکھ سکتے ہیں لیکن بات چیت نہیں کرسکتے تصدیق شدہ صارفین ان سروے پر ووٹ کر سکتے ہیں جو وہ پیدا نہیں کرتے ہیں تخلیق کار اپنے سروے پر ووٹ نہیں کرسکتے صرف تخلیق کاروں کو ان کے سروے میں ترمیم / حذف کے اختیارات دیکھیں آپ کو براؤزر پر جانے کے ذریعے ایپلی کیشن کی تبدیلیوں کو دیکھنے کے قابل ہونا چاہئے. ہوم سکرین پر، صارفین کو موجودہ اور ماضی کے سروے کی فہرست دیکھی جا سکتی ہے، چاہے وہ لاگ ان کر رہے ہیں یا نہیں. تاہم، جب وہ ایک سروے پر کلک کرتے ہیں تو، وہ سروے کی تفصیلات کو دیکھنے یا اس پر ووٹ کرنے کے قابل نہیں ہوں گے. ایک بار لاگ ان کرنے کے بعد، صارف نے سروے کی تفصیلات کو دیکھنے اور اس پر ووٹ کر سکتے ہیں. تاہم، اگر صارف نے سروے کا تخلیق کیا ہے تو، وہ اس پر ووٹ نہیں کرسکتے ہیں. وہ ایک پیغام دیکھیں گے کہ وہ اپنے سروے پر ووٹ نہیں کرسکتے ہیں. نتیجہ اس ٹیوٹوریل میں، ہم نے استعمال کرنے کے لئے کس طرح کا تجربہ کیا ایک حقیقی دنیا میں اپلی کیشن Supabase authentication and authorization Next.js ہم نے قائم کرنے سے شروع کیا لاگ ان اور رجسٹریشن کے لئے، راؤنڈ سطح سیکورٹی کے ساتھ ایک رسیلیٹ شیڈول بنائی گئی، اور ڈینمک لائسنسنگ منطق کا استعمال کرتے ہوئے شامل کیا گیا • مدد کے ساتھ اور A ہم نے براہ راست frontend سے اجازت چیک کی. Supabase Auth ReBAC Supabase Edge Functions Policy Decision Point (PDP) ترکیب کے ذریعے انعطاف پذیر رسائی کنٹرول کے ساتھ، ہم کر سکتے ہیں: Supabase Auth کے کے کے کے ای میل اور پاس ورڈ کے ذریعے صارفین کی تصدیق ووٹنگ اور سروے کے انتظام کو مجاز صارفین کو محدود کریں تخلیق کاروں کو اپنے سروے پر ووٹ دینے سے روکنے اعداد و شمار کے ساتھ تعلقات کی بنیاد پر صارفوں کی کرداروں کا تعین اور تجزیہ This setup gives you a scalable foundation for building apps that require both authentication and fine-grained authorization. مزید پڑھیں کے کے کے کے کے کے Permit.io ReBAC گائیڈ لائسنس + تصدیق فراہم کرنے والے Permit Elements: Role Management کے لئے Embedded UI اجازت کے ساتھ ڈیٹا فلٹرنگ Audit Logs کوئی سوالات ہیں؟ ہمارے ساتھ شامل رہیں جہاں سینکڑوں ڈویلپرز تعمیر کر رہے ہیں اور اجازت کے بارے میں بات کر رہے ہیں. Slack community Slack community